// Copyright 2011 Bryan McKelvey, MIT License

/**
 * @fileoverview The Metrics singleton and the methods available to it
 * @author bryan.mckelvey@gmail.com (McKelvey Bryan)
 */

/**
 * This class contains the metrics available for use in returning values for
 * the security IDs chosen
 * @constructor
 */
var Metrics = (function(){
	/**
	 * A private object holding the metrics available for use
	 * @type Object
	 */
  var metrics = {};
	
	/**
	 * A private array holding the metrics chosen for use
	 * @type Object
	 */
  var columns = [];
	
	/**
	 * A private member containing a jQuery-wrapped DIV node
	 * @type Object
	 */
  var $div;

	return {
		/**
		 * Adds a new metric to the Metrics object
		 * @param {string} label The label which will be used when localizing the
		 * name of the parameter
		 * @param {string} type The type of value (text, value, change, pct)
		 * @param {function} func The function for evaluating the sum of all values
		 * @param {function} numer The function for evaluating the numerator
		 * @param {function} denom The function for evaluating the denominator
		 * @returns The current object
		 * @type Metrics
		 */
		add: function(label, type, func, numer, denom) {
		  if (numer != undefined) {
		    metrics[label] = {"type": type, "func": func, "numer": numer, "denom": denom};
		  } else {
		    metrics[label] = {"type": type, "func": func};
		  }
			return this;
		},

		/**
		 * Evaluates a metric for the supplied context
		 * @param {string} label The metric's label
		 * @param {Object} context
		 * @returns 
		 * @type number
		 */
		calculate: function(label, context) {
		  return metrics[label].func.call(context);
		},
		
		/**
		 * Retrieves the metric assigned to a particular column
		 * @param {Object} index The index of the column
		 * @returns A metric and its associated functions
		 * @type Object
		 */
		column: function(index){
			return columns[index];
		},
		
		/**
		 * Retrieves the number of metrics in use
		 * @returns The number of metrics in use
		 * @type number
		 */
		count: function(){
			return columns.length;
		},
		
		/**
		 * Creates a dropdown of available for metrics for selection on the options
		 * page
		 * @param {Object} $node The jQuery-wrapped DOM node that will contain this
		 * method's output
		 * @returns The current object
		 * @type Metrics
		 */
		dropdowns: function($node) {
			$node.empty();

			$.each(columns, function(index, column){
				var $select = $('<select>').append($('<option>')).change(function(){
					var $this = $(this);
					if ($this.val() === '') {
						if ($this.next().length > 0) {
							$this.next().remove();
						}
					} else {
						if ($this.next().length === 0) {
							$this.after($this.clone());
						}
					}
				});

				$.each(metrics, function(key, value){
		      var $option = $('<option>').val(key).text(Localizer.translate(key));
					if (key === column) {
						$option.attr("selected", true);
					}
					$select = $select.append($option);
				});
		    $node.append($select);
			});
		  
		  $div = $node;
			return this;
		},

		/**
		 * Retrieves a metric based on its corresponding label
		 * @param {string} label
		 * @returns A metric
		 * @type object
		 */		
		get: function(label){
			return metrics[label];
		},
		
		/**
		 * Loads the values for the metrics in use from local storage
		 * @returns The current object
		 * @type Metrics
		 */
		load: function() {
		  try {
		    columns = Settings.columns();
		  } catch(e) {
		    Metrics.reset();
		  }
			return this;
		},
		
		/**
		 * Resets the metrics in use to their defaults
		 * @returns The current object
		 * @type Metrics
		 */
		reset: function() {
		  columns = ["secid", "title", "value", "change", "pctChange", "portValue", "dailyGain", "dailyPctGain"];
			Settings.columns(columns);
			return this;
		},
		
		/**
		 * Saves the metrics based on selections made on the options page
		 * @returns The current object
		 * @type Metrics
		 */
		save: function() {
		  var $selects = $("select", $div);
		  var temp = [];

			$("select", div).each(function(){
				if ($(this).val() !== "") {
					temp.push($(this).val());
				}
			});

			Settings.columns(temp);
		  columns = temp;
			return this;
		}
	}	
})();

Metrics.load();